AddCSLuaFile("cl_init.lua")
AddCSLuaFile("shared.lua")
include("shared.lua")

function ENT:SetPlayer(ply)
	if ply == nil then self:Remove() end

	self.Founder = ply
	self:SetPhysicsAttacker(ply)
	self:SetOwner(ply)
	self.FounderIndex = ply:UniqueID()

	self:SetNetworkedString("FounderName", ply:Nick())
end

function ENT:SetDriver(ply)
	self.Driver = ply

	if ply != NULL and ply != nil then	
		if ply:IsValid() then
			local phys = self:GetPhysicsObject()
			if not phys:IsValid() then return end
			phys:EnableGravity(true)
			self.Land = true
			self.TakeOff = false
			umsg.Start("CurVehicleOffset", ply)
			umsg.Angle(self.Offset)
			umsg.End()
		end
	end
end

function ENT:Setup(model, drag, health, color, offset, parts, weapon)
	if self:GetOwner() == NULL then return end

	self.Model = model
	self.Drag = drag
	self.VehHealth = health 
	self.MaxVehHealth = health
	self.Color = color 
	self.Offset = offset
	self.ViewAng = vang
	self.WeaponTbl = weapon
	self.Parts = parts or {}
end

function ENT:UpdateParts(tbl)
	self.Parts = tbl
end

function ENT:MaxVehicleHealth()
	return self.MaxVehHealth
end

function ENT:Initialize()

	self:SetModel( self.Model )
	self:SetColor( self.Color.r, self.Color.g, self.Color.b, self.Color.a )

	self:PhysicsInit( SOLID_VPHYSICS )
	self:SetMoveType( MOVETYPE_VPHYSICS )
	self:SetSolid( SOLID_VPHYSICS )
	
	self:StartMotionController( true ) //ESSENTIAL TO USE THIS

	self.TakeOff = false
	self.Land = true
	self.Launch = .1
	self.LandTime = .1
	self.Crash = false
	self.Mayday = false

	self.BaseSpeed = 25 - self.Drag * 20 // base speed is in between 5 and 25
	self.TurnSpeed = 1.1 - self.Drag * 1 // turn speed is in between .1 and 1.1
	
	umsg.Start("MaxVehicleHealth", self:GetOwner())
	umsg.Short(self:MaxVehicleHealth())
	umsg.End()
	umsg.Start("VehicleHealth", self:GetOwner())
	umsg.Short(self.VehHealth)
	umsg.End()
	
	util.PrecacheSound("vehicles/airboat/fan_blade_idle_loop1.wav")
	util.PrecacheSound("vehicles/airboat/fan_blade_fullthrottle_loop1.wav")
	util.PrecacheSound("vehicles/airboat/fan_motor_fullthrottle_loop1.wav")
	self.DriveSounds = {}
	self.DriveSounds.Idle = CreateSound(self,"vehicles/airboat/fan_blade_idle_loop1.wav")
	self.DriveSounds.Drive = CreateSound(self,"vehicles/airboat/fan_blade_fullthrottle_loop1.wav")
	self.DriveSounds.Mayday = CreateSound(self,"vehicles/airboat/fan_motor_fullthrottle_loop1.wav")
	self.DriveSounds.CurSound = self.DriveSounds.Mayday
	
end

function ENT:SetSoundLoop(snd)
	if snd == self.DriveSounds.CurSound then
		return
	else
		self.DriveSounds.CurSound:Stop()
		snd:Play()
		self.DriveSounds.CurSound = snd
	end
end

function ENT:EndSoundLoop()
	self.DriveSounds.CurSound:Stop()
end

function ENT:TestAngles()

	//the default angles are shown first
	local effectdata = EffectData()
	effectdata:SetOrigin(self:GetPos() + (self:GetForward()*60) )
	effectdata:SetAngle(Angle(220,0,0)) //angle is actually a color being sent. P,Y,R = R,G,B
	util.Effect("angle_test", effectdata)
	local effectdata = EffectData()
	effectdata:SetOrigin(self:GetPos() + (self:GetRight()*60) )
	effectdata:SetAngle(Angle(0,220,0))
	util.Effect("angle_test", effectdata)
	local effectdata = EffectData()
	effectdata:SetOrigin(self:GetPos() + (self:GetUp()*60) )
	effectdata:SetAngle(Angle(0,0,220))
	util.Effect("angle_test", effectdata)
	
	//show us the modified angles now.
	local effectdata = EffectData()
	effectdata:SetOrigin(self:GetPos() + ((self:GetTrueForward() *60) +Vector(0,0,10)))
	effectdata:SetAngle(Angle(220,0,0)) //angle is actually a color being sent. P,Y,R = R,G,B
	util.Effect("angle_test", effectdata)
	local effectdata = EffectData()
	effectdata:SetOrigin(self:GetPos() + ((self:GetTrueRight()*60) +Vector(0,0,10)))
	effectdata:SetAngle(Angle(0,220,0))
	util.Effect("angle_test", effectdata)
	local effectdata = EffectData()
	effectdata:SetOrigin(self:GetPos() + ((self:GetTrueUp()*60) +Vector(0,0,10)))
	effectdata:SetAngle(Angle(0,0,220))
	util.Effect("angle_test", effectdata)
	
end

local v15up = Vector(0,0,15)
local v20up = Vector(0,0,20)
local v200up = Vector(0,0,200)
function ENT:PhysicsSimulate(phys, frametime)

	phys:Wake()
	
	if self.Mayday then
		phys:ApplyForceCenter((self.BaseSpeed / 1.7) * phys:GetMass() * (self:GetTrueUp()*-2))
		phys:AddAngleVelocity(Angle( self.TurnSpeed/2 * frametime * 66 , 0, 0))
		local effectdata = EffectData()
		effectdata:SetOrigin(self:GetPos())
		util.Effect("smoke_trail_big", effectdata)
	end
	
	if self.Crash then
		if self:GetOwner() then
			if self.Mayday then
				if self.Mayday:IsPlayer() then
					self:GetOwner():DestroyVehicle(self.Mayday)
				else
					self:GetOwner():DestroyVehicle()
				end
			else
				self:GetOwner():DestroyVehicle()
			end
		end
	end

	local v = self.Driver
	if v == nil or v == NULL then phys:EnableGravity(true) return SIM_NOTHING end
	if not v:IsValid() then phys:EnableGravity(true) return SIM_NOTHING end
	
	v:SetPos(self:GetPos() + v200up)

	if self.Launch > CurTime() then
		phys:ApplyForceCenter((self.BaseSpeed / 2) * phys:GetMass() * self:GetTrueUp() + v15up)
		phys:EnableGravity(false)
		return
	elseif self.TakeOff then
		phys:ApplyForceCenter((self.BaseSpeed / 1.7) * phys:GetMass() * self:GetTrueForward())
	end

	if v:KeyDown( IN_JUMP ) then
		if self.TakeOff and self.Launch < CurTime() then
			self.Land = true
			self.TakeOff = false
			phys:EnableGravity(true)
			self.LandTime = CurTime() + 3
			self:EmitSound(Sound("vehicles/airboat/fan_motor_shut_off1.wav"), 100, math.random(90, 100))
		elseif self.Land and self.LandTime < CurTime() then
			self.TakeOff = true
			self.Land = false
			self.Launch = CurTime() + .5
			self:EmitSound(Sound("vehicles/airboat/fan_motor_start1.wav"), 100, math.random(90, 100))
		end
	end

	if self.Launch < CurTime() then
		if v:KeyDown( IN_FORWARD ) then
			if v.Inverted then
				//phys:AddAngleVelocity(Angle( self.BaseSpeed * frametime * -66 , 0, 0))
				phys:AddAngleVelocity(Angle(0, 1 * self.TurnSpeed * frametime * -66, 0))
			else
				//phys:AddAngleVelocity(Angle( self.BaseSpeed * frametime * 66 , 0, 0))
				phys:AddAngleVelocity(Angle(0, 1 * self.TurnSpeed * frametime * 66, 0))
			end 
		elseif v:KeyDown( IN_BACK ) then
			if v.Inverted then
				//phys:AddAngleVelocity(Angle( self.BaseSpeed * frametime * -66) , 0, 0)
				phys:AddAngleVelocity(Angle(0, 1 * self.TurnSpeed * frametime * 66, 0))
			else
				//phys:AddAngleVelocity(Angle( self.BaseSpeed * frametime * 66) , 0, 0)
				phys:AddAngleVelocity(Angle(0, 1 * self.TurnSpeed * frametime * -66, 0))
			end 
		elseif v:KeyDown( IN_SPEED ) then
			if not self.Land then
				local forward = phys:GetMass() * self.BaseSpeed * self:GetTrueForward()
				phys:ApplyForceCenter(forward) 
			end
		elseif v:KeyDown( IN_MOVELEFT ) then
			if not self.Land then
				//phys:AddAngleVelocity(Angle(0, -1 * self.BaseSpeed * 0.5 * self:GetTrueForward(), 0))
				//phys:AddAngleVelocity(Angle(0, -1 * self.BaseSpeed * frametime * 66, 0))
				phys:AddAngleVelocity(Angle( self.TurnSpeed * frametime * -66 , 0, 0))
			end
		elseif v:KeyDown( IN_MOVERIGHT ) then
			if not self.Land then
				//phys:AddAngleVelocity(Angle(0, 1 * self.BaseSpeed * 0.5 * self:GetForward(), 0))
				//phys:AddAngleVelocity(Angle(0, 1 * self.BaseSpeed * frametime * 66, 0))
				phys:AddAngleVelocity(Angle( self.TurnSpeed * frametime * 66 , 0, 0))
			end
		end
		if v:KeyDown( IN_DUCK ) then
			phys:ApplyForceCenter((self.BaseSpeed / 1.5) * phys:GetMass() * (self:GetTrueUp()*-2))
		end
	end
end

function ENT:GetWeapon()
	return self.Weapon
end

function ENT:Think()
	if self.Driver then
		self.Driver:SetPos(self:GetPos() + Vector(0,0,200))
	end
	if self:WaterLevel() > 0 then
		self.Crash = true
	end
	if self.Parts[2] and self.Weapon == nil then
		self.Weapon = self.Parts[2]
	end
	if self.Weapon and self.Driver then
		if self.Weapon.User == nil then
			self.Weapon:SetUser(self.Driver)
		end
		local aimv = self:GetTrueAngles()
		local plyv = self.Driver:EyeAngles()
		local wepang = self:LocalToWorldAngles(self.Weapon.Offset)
		self.Weapon:SetAngles(aimv + self.Weapon.Offset)
	end
end 

function ENT:OnTakeDamage(dmg)
	self:EmitSound(ChooseRandom(GameSounds.VehicleHit),100,math.random(90,110))
	local owner = self:GetOwner()
	if dmg:GetAttacker():IsPlayer() then
		if dmg:GetAttacker():Team() == owner:Team() then
			return
		end
		if self.Driver then
			self.Driver:TakeDamage(1,attacker)
		end
		self.VehHealth = self.VehHealth - dmg:GetDamage()
		umsg.Start("VehicleHealth", self:GetOwner())
		umsg.Short(self.VehHealth)
		umsg.End()
		if dmg:GetDamage() > 35 then
			local effectdata = EffectData()
			effectdata:SetOrigin(self:GetPos())
			util.Effect("prop_gib", effectdata)
		end
	end
	if self.VehHealth <= 20 and self.VehHealth > 0 then
		if dmg:GetAttacker():IsPlayer() then
			self.Mayday = dmg:GetAttacker()
		else
			self.Mayday = ents.FindByClass("sent_vehiclepad")[1] //nonplayer lol
		end
		umsg.Start("IsMayday", self:GetOwner())
		umsg.Short(5)
		umsg.End()
		self:EmitSound(Sound("vehicles/apc/apc_shutdown.wav"),120,math.random(90,110))
		self:SetSoundLoop(self.DriveSounds.Mayday)
	elseif self.VehHealth <= 0 then
		owner:DestroyVehicle(dmg:GetAttacker())
	end
end 

function ENT:ExplodeEffects()
	local pos = self:GetPos()
	local tracedata = {}
	tracedata.start = pos
	tracedata.endpos = pos+Vector(math.random(-10,10),math.random(-10,10),-250)
	tracedata.filter = self
	local trace = util.TraceLine(tracedata)
	if trace.HitWorld then
		util.Decal("Scorch",trace.HitPos+trace.HitNormal,trace.HitPos-trace.HitNormal)
		util.Decal("FadingScorch",trace.HitPos+trace.HitNormal,trace.HitPos-trace.HitNormal)
		local effectdata = EffectData()
		effectdata:SetOrigin(trace.HitPos)
		util.Effect("smoke_crater", effectdata)
	end
	util.ScreenShake( pos, math.Round(8*self.TurnSpeed),220, math.random(3,6), 800 )  
end

function ENT:Destroy()
	self:EndSoundLoop()
	self:ExplodeEffects()
	for k, v in pairs(self.Parts) do
		v:Remove()
	end
	self:Remove()
end

function ENT:PhysicsCollide(data, physobj)
	if self.Mayday then
		local owner = self:GetOwner()
		if owner and owner:IsValid() then
			self.Crash = true
		end
	elseif self.Land then
		if data.Speed > 950 and data.DeltaTime > 0.2 then
			local owner = self:GetOwner()
			if owner and owner:IsValid() then
				self.Crash = true
			end
		end
	else
		if data.Speed > 250 and data.DeltaTime > 0.2 then
			local owner = self:GetOwner()
			if owner and owner:IsValid() then
				self.Crash = true
			end
		end
	end
end